package jmine.tec.batch.domain;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import jmine.tec.persist.Versioned;
import bancosys.tec.persist.Persistable;
import bancosys.tec.persist.dao.BaseDAO;

/**
 * Classe que transporta os grupos de eleementos que corresponderão a unidades de processamento.
 * <p>
 * Essa classe é utilizada para armazenar o resultado do agrupamento de elementos em páginas antes do inicio do processamento. <br>
 * É utilizada para instanciar as unidades de processamento pelo {@link MProcess}. <br>
 * <p>
 * Tem a responsabilidade de tornar possível o polimorfismo da unidade de processamento, ao receber o BaseDAO da extensão de ProcessingUnit.
 * <br>
 * Dessa forma, o MProcess pode instanciar a classe correta de ProcessingUnit.
 * 
 * @param <E> Generics que representa a classe do elemento.
 * @param <P> Generics que representa a classe da unidade de processamento (extende ProcessingUnit).
 * @author Frank Cara
 * @see Process
 * @see ProcessingUnit
 * @see MProcess
 */
public class PhaseableElementGroup<E extends Persistable & Versioned, P extends ProcessingUnit<?>> {
    private Set<List<E>> groups = new HashSet<List<E>>();

    private BaseDAO<P> dao;

    /**
     * Construtor.
     * 
     * @param dao o DAO para instanciação da processing unit extendida.
     */
    public PhaseableElementGroup(BaseDAO<P> dao) {
        this.dao = dao;
    }

    /**
     * Adiciona um grupo de elementos.
     * 
     * @param elements a lista de elementos que corresponde a um grupo de elementos.
     */
    public void addGroup(List<E> elements) {
        this.groups.add(elements);
    }

    /**
     * Itera sobre os grupos de elementos. <br>
     * Cada grupo é uma lista de elementos.
     * 
     * @return um Iterator de listas de elementos.
     */
    public Iterator<List<E>> iterator() {
        return this.groups.iterator();
    }

    /**
     * A quantidade de grupos de elementos.
     * 
     * @return a quantidade de grupos de elementos.
     */
    public int size() {
        return this.groups.size();
    }

    /**
     * Instancia uma extensão da ProcessingUnit.
     * 
     * @return a unidade de processamento cadastrada.
     */
    public P createProcessingUnit() {
        return this.dao.createBean();
    }

}
